package com.fy.proj3_deepseek_api.service;

import com.fy.proj3_deepseek_api.model.User;
import com.fy.proj3_deepseek_api.model.Role;
import com.fy.proj3_deepseek_api.model.auth.LoginRequest;
import com.fy.proj3_deepseek_api.model.auth.RegisterRequest;
import com.fy.proj3_deepseek_api.model.auth.JwtResponse;
import com.fy.proj3_deepseek_api.model.auth.CaptchaResponse;
import com.fy.proj3_deepseek_api.repository.UserRepository;
import com.fy.proj3_deepseek_api.repository.RoleRepository;
import com.fy.proj3_deepseek_api.util.JwtUtils;
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
public class AuthService {
    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    UserRepository userRepository;

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    PasswordEncoder encoder;

    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    private Producer captchaProducer;

    // 存储验证码，使用ConcurrentHashMap确保线程安全
    private final Map<String, String> captchaStore = new ConcurrentHashMap<>();

    @Transactional
    public JwtResponse authenticateUser(LoginRequest loginRequest) {
        // 验证验证码
        if (!validateCaptcha(loginRequest.getCaptchaToken(), loginRequest.getCaptchaCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 执行认证
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);

        // 更新用户最后登录时间
        updateUserLastLogin(loginRequest.getUsername());

        // 构建响应
        return buildJwtResponse(jwt, authentication);
    }

    @Transactional
    public JwtResponse registerUser(RegisterRequest registerRequest) {
        // 验证验证码
        if (!validateCaptcha(registerRequest.getCaptchaToken(), registerRequest.getCaptchaCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 检查用户名是否已存在
        if (userRepository.existsByUsername(registerRequest.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }

        // 创建新用户
        User user = createNewUser(registerRequest);
        userRepository.save(user);

        // 自动登录新用户
        return loginAfterRegistration(registerRequest.getUsername(), registerRequest.getPassword());
    }

    public CaptchaResponse generateCaptcha() {
        String captchaCode = captchaProducer.createText();
        BufferedImage image = captchaProducer.createImage(captchaCode);
        String captchaToken = UUID.randomUUID().toString();

        // 存储验证码，5分钟过期
        captchaStore.put(captchaToken, captchaCode);
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                captchaStore.remove(captchaToken);
            }
        }, 5 * 60 * 1000);

        // 转换为Base64字符串
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(image, "png", outputStream);
            String base64Image = Base64.getEncoder().encodeToString(outputStream.toByteArray());
            return new CaptchaResponse(captchaToken, "data:image/png;base64," + base64Image);
        } catch (IOException e) {
            throw new RuntimeException("生成验证码失败", e);
        }
    }

    private boolean validateCaptcha(String captchaToken, String captchaCode) {
        if (captchaToken == null || captchaCode == null) {
            return false;
        }
        String storedCode = captchaStore.remove(captchaToken);
        return storedCode != null && storedCode.equalsIgnoreCase(captchaCode);
    }

    private User createNewUser(RegisterRequest registerRequest) {
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setEmail(registerRequest.getUsername() + "@example.com"); // 设置默认邮箱
        user.setPhone("13800138000"); // 设置默认手机号
        user.setPassword(encoder.encode(registerRequest.getPassword()));

        // 设置用户角色为普通用户
        Role userRole = roleRepository.findByName("ROLE_USER")
                .orElseGet(() -> {
                    Role newRole = new Role();
                    newRole.setName("ROLE_USER");
                    return roleRepository.save(newRole);
                });
        user.getRoles().add(userRole);
        return user;
    }

    private JwtResponse buildJwtResponse(String jwt, Authentication authentication) {
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        List<String> roles = userDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());

        User user = userRepository.findByUsername(userDetails.getUsername()).orElseThrow();
        return new JwtResponse(jwt, user.getId(), user.getUsername(), user.getEmail(), roles);
    }

    private void updateUserLastLogin(String username) {
        User user = userRepository.findByUsername(username).orElseThrow();
        user.setLastLogin(new Date().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime());
        userRepository.save(user);
    }

    private JwtResponse loginAfterRegistration(String username, String password) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(username, password));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);
        return buildJwtResponse(jwt, authentication);
    }
}